package com.hq.ims.data.service;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.hq.ims.data.alisms.AliSmsConfig;
import com.hq.ims.data.dao.UserMapper;
import com.hq.ims.data.entity.*;
import com.hq.ims.data.entityenum.EnumAccountStatus;
import com.hq.ims.data.entityenum.EnumAuditStatus;
import com.hq.ims.data.utils.AccountUtils;
import com.hq.ims.data.utils.ErrMsgConstant;
import com.hq.ims.data.utils.LocalConstant;
import com.hq.ims.data.utils.PasswordUtils;
import com.hq.ims.data.vo.UserMapstruct;
import com.hq.mybatis.base.BaseService;
import com.hq.mybatis.base.page.RequestPage;
import com.hq.utils.exception.CommonException;
import com.hq.utils.util.*;
import com.hq.web.utils.SpringBootValidateUtils;
import lombok.NonNull;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Nonnull;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional(rollbackFor = Exception.class)
public class BaseUserService extends BaseService<UserMapper, User> {

    @Value("${userAttribute.userDefaultAvatar}")
    private String initUserAvatar;

    @Resource
    private AliSmsConfig aliSmsConfig;
    @Resource
    private BaseCompanyEmployeeService baseCompanyEmployeeService;
    @Resource
    private BaseCompanyDepartmentEmployeeService baseCompanyDepartmentEmployeeService;
    @Resource
    private BaseCompanyDepartmentService baseCompanyDepartmentService;
    @Resource
    private BaseCompanyService baseCompanyService;
    @Resource
    private BaseAllowLoginPlatformCompanyService baseAllowLoginPlatformCompanyService;
    @Resource
    private BaseFileRecordService baseFileRecordService;

    /**
     * 添加简单用户信息
     *
     * @param account   账号
     * @param mobile    手机
     * @param pwd       明文密码
     * @param avatarUrl 头像地址
     * @param realName  姓名
     */
    public User addSimpleUserInfo(
            @NonNull String account,
            @NonNull String mobile,
            @NonNull String pwd,
            @NonNull String avatarUrl,
            @NonNull String realName
    ) {
        //不能做手机号较验,因为存在短信登陆,短信登陆用户不存在则要添加用一个用户
        User user = new User();
        user.setAccount(account);
        user.setMobile(mobile);
        user.setPwd(EncryptDecryptUtils.md5Encrypt(pwd));
        user.setAvatarUrl(avatarUrl);
        user.setAccountStatus(EnumAccountStatus.Normal);
        user.setRealName(realName);
        user.insert();
        return user;
    }

    /**
     * 根据账号获取用户信息
     */
    public User getByAccount(@NonNull String account) {
        return super.lambdaQuery()
                .eq(User::getAccount, account)
                .orderByDesc(User::getCreateDateTime)
                .last(LocalConstant.LIMIT_1)
                .one();
    }

    public User getByMobile(@NonNull String mobile) {
        return super.lambdaQuery()
                .eq(User::getMobile, mobile)
                .orderByDesc(User::getCreateDateTime)
                .last(LocalConstant.LIMIT_1)
                .one();
    }

    /**
     * 手机号是否存在
     */
    public boolean mobileExists(
            @NonNull String mobile,
            String excludeUserId
    ) {
        return this.lambdaQuery()
                .eq(User::getMobile,mobile)
                .ne(StringUtils.isNotEmpty(excludeUserId), User::getUserId, excludeUserId)
                .count() > 0;
    }


    /**
     * 更新用户密码
     *
     * @param userId 用户ID
     * @param pwd    明文密码
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateUserPwd(
            String userId,
            String pwd
    ) {
        this.lambdaUpdate().eq(User::getUserId, userId).set(User::getPwd, EncryptDecryptUtils.md5Encrypt(pwd)).update();
    }

    /**
     * 更新用户密码
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateUserPwdValidSmsCode(
            String smsCode,
            UserMapstruct.ForgotPasswordVo saveVo
    ) {
        //数据校验
        SpringBootValidateUtils.validate(saveVo);

        //1: 验证手机号
        BooleanUtils.isFalseThrow(RegexUtils.checkMobile(saveVo.getMobile()), ErrMsgConstant.MOBILE_VALID_ERR);
        User user = this.getByMobile(saveVo.getMobile());
        ObjectUtils.isNullThrow(user, ErrMsgConstant.MOBILE_UN_REGISTER_ERR);

        //验证短信是否正确
        Boolean smsCodeValidBl = aliSmsConfig.checkVerifyMobileSms(saveVo.getMobile(), smsCode);
        BooleanUtils.isFalseThrow(smsCodeValidBl, ErrMsgConstant.MOBILE_SMS_CODE_ERR);

        //2：将密码解密验证
        String decryptPwd = EncryptDecryptUtils.rsaPrivateDecryption(saveVo.getPwd(), LocalConstant.RSA_DECRY_KEY);
        if (StringUtils.isEmpty(decryptPwd)) {
            throw CommonException.build(ErrMsgConstant.DECODE_FAILURE);
        }
        //4: 更新密码
        this.updateUserPwd(user.getUserId(), decryptPwd);

        //最后删除验证码
        aliSmsConfig.deleteVerifyMobileSms(saveVo.getMobile());
    }

    /**
     * 让用户强制更新密码
     *
     * @param userId 用户ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void setUserForceUpdatePwd(
            String userId
    ) {
        this.lambdaUpdate().eq(User::getUserId, userId).set(User::getIsNeedForceUpPwd, true).update();
    }

    /**
     * 更新用户状态
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateUserAccountStatus(
            String userId,
            EnumAccountStatus accountStatus
    ) {
        this.lambdaUpdate().eq(User::getUserId, userId).set(User::getAccountStatus, accountStatus).update();
    }

    /**
     * 根据公司id查询公司负责人
     */
    public User getCompanyAdminByCompanyId(
            @Nonnull String companyId
    ) {
        CompanyEmployee companyEmployee = baseCompanyEmployeeService.getCompanyAdminByCompanyId(companyId);
        if (companyEmployee == null) {
            return null;
        }
        User user = this.getById(companyEmployee.getUserId());
        return user;
    }

    /**
     * 获取部门员工信息
     */
    public List<UserMapstruct.UserAndCompanySimpleVo> getPageByDepartmentId(
            RequestPage page,
            UserMapstruct.PageSearchVo searchVo,
            String companyDepartmentId
    ) {
        //公司部门
        CompanyDepartment companyDepartment = baseCompanyDepartmentService.getById(companyDepartmentId);
        if (companyDepartment == null) {
            return ListUtils.newEmptyList();
        }
        //公司
        Company company = baseCompanyService.getById(companyDepartment.getCompanyId());
        if (company == null) {
            return ListUtils.newEmptyList();
        }


        List<CompanyDepartmentEmployee> companyDepartmentEmployeeList = baseCompanyDepartmentEmployeeService.getByDepartmentId(companyDepartmentId, null);
        if (ListUtils.isNotExistsEle(companyDepartmentEmployeeList)) {
            return ListUtils.newEmptyList();
        }
        //获取公司管理员
        CompanyEmployee companyAdminEmployee = baseCompanyEmployeeService.getCompanyAdminByCompanyId(company.getCompanyId());
        String companyAdminUserId = companyAdminEmployee == null ? StringUtils.EMPTY : companyAdminEmployee.getUserId();
        //部门员工信息map
        Map<String, List<CompanyDepartmentEmployee>> companyDepartmentEmployeeMap = companyDepartmentEmployeeList.stream().collect(Collectors.groupingBy(CompanyDepartmentEmployee::getUserId));
        //用户ID列表
        List<String> userIdList = companyDepartmentEmployeeList.stream().map(CompanyDepartmentEmployee::getUserId).distinct().collect(Collectors.toList());

        //查询
        LambdaQueryChainWrapper<User> lq = this.lambdaQuery();
        lq.in(User::getUserId, userIdList);
        lq.eq(StringUtils.isNotEmpty(searchVo.getRealName()), User::getRealName, searchVo.getRealName());
        lq.eq(StringUtils.isNotEmpty(searchVo.getMobile()), User::getMobile, searchVo.getMobile());
        lq.page(page);

        List<User> userList = page.getRecords();

        //转换简单对象
        List<UserMapstruct.UserAndCompanySimpleVo> userAndCompanySimpleVoList = new ArrayList<>(userList.size());

        userList.stream().forEach(user -> {

            List<CompanyDepartmentEmployee> userCompanyDepartmentEmployeeList = companyDepartmentEmployeeMap.get(user.getUserId());
            //用户主职信息
            List<CompanyDepartmentEmployee> mainCompanyDepartmentEmployeeList = userCompanyDepartmentEmployeeList.stream().filter(d -> !d.getIsPartTimeJob()).collect(Collectors.toList());
            //用户兼职信息
            List<CompanyDepartmentEmployee> partTimeJobCompanyDepartmentEmployeeList = userCompanyDepartmentEmployeeList.stream().filter(d -> d.getIsPartTimeJob()).collect(Collectors.toList());

            //用户是否兼职
            boolean userIsPartTimeJob = false;
            CompanyDepartmentEmployee companyDepartmentEmployee = null;
            if (ListUtils.isExistsEle(mainCompanyDepartmentEmployeeList)) {
                userIsPartTimeJob = false;
                companyDepartmentEmployee = mainCompanyDepartmentEmployeeList.get(0);
            } else if (ListUtils.isExistsEle(partTimeJobCompanyDepartmentEmployeeList)) {
                userIsPartTimeJob = true;
                companyDepartmentEmployee = partTimeJobCompanyDepartmentEmployeeList.get(0);
            } else {
                throw CommonException.build(ErrMsgConstant.EMPLOYEE_INFO_NOT_EXISTS);
            }
            List<String> userAllCompanyNameList = baseCompanyService.getUserAllCompanyNameListByUserId(user.getUserId(), true);

            UserMapstruct.UserAndCompanySimpleVo userAndCompanySimpleVo = new UserMapstruct.UserAndCompanySimpleVo();
            userAndCompanySimpleVo.setUserId(user.getUserId());
            userAndCompanySimpleVo.setRealName(user.getUserId());
            userAndCompanySimpleVo.setAvatarUrl(user.getAvatarUrl());
            userAndCompanySimpleVo.setAccountStatus(user.getAccountStatus());
            userAndCompanySimpleVo.setSex(user.getSex());
            userAndCompanySimpleVo.setCompanyId(company.getCompanyId());
            userAndCompanySimpleVo.setCompanyName(company.getCompanyName());
            userAndCompanySimpleVo.setCompanyDepartmentId(companyDepartment.getCompanyDepartmentId());
            userAndCompanySimpleVo.setCompanyDepartmentName(companyDepartment.getCompanyDepartmentName());
            userAndCompanySimpleVo.setUserPartTimeJobCompanyNameList(userAllCompanyNameList);
            userAndCompanySimpleVo.setIsCompanyDepartmentPrincipal(userIsPartTimeJob);
            userAndCompanySimpleVo.setIsCompanyAdmin(user.getUserId().equals(companyAdminUserId));
            userAndCompanySimpleVo.setJobName(companyDepartmentEmployee.getJobName());
            userAndCompanySimpleVoList.add(userAndCompanySimpleVo);

        });
        page.setRecords(userAndCompanySimpleVoList);
        return userAndCompanySimpleVoList;

    }

    /**
     * 根据公司id获取所有用户
     */
    public List<UserMapstruct.UserAndCompanySimpleVo> getPageByCompanyId(
            RequestPage page,
            UserMapstruct.PageSearchVo searchVo,
            @NonNull String companyId
    ) {
        //公司
        Company company = baseCompanyService.getById(companyId);
        if (company == null) {
            return ListUtils.newEmptyList();
        }


        List<CompanyDepartmentEmployee> companyDepartmentEmployeeList = baseCompanyDepartmentEmployeeService.getByCompanyId(companyId, null);
        if (ListUtils.isNotExistsEle(companyDepartmentEmployeeList)) {
            return ListUtils.newEmptyList();
        }
        //获取公司管理员
        CompanyEmployee companyAdminEmployee = baseCompanyEmployeeService.getCompanyAdminByCompanyId(company.getCompanyId());
        String companyAdminUserId = companyAdminEmployee == null ? StringUtils.EMPTY : companyAdminEmployee.getUserId();
        //部门员工信息map
        Map<String, List<CompanyDepartmentEmployee>> companyDepartmentEmployeeMap = companyDepartmentEmployeeList.stream().collect(Collectors.groupingBy(CompanyDepartmentEmployee::getUserId));
        //用户ID列表
        List<String> userIdList = companyDepartmentEmployeeList.stream().map(CompanyDepartmentEmployee::getUserId).distinct().collect(Collectors.toList());
        //获取部门对象
        List<CompanyDepartment> companyDepartmentList = baseCompanyDepartmentService.getByCompanyId(companyId);
        Map<String, CompanyDepartment> companyDepartmentMap = baseCompanyDepartmentService.getToMap(companyDepartmentList, d -> d.getCompanyDepartmentId());

        //查询
        LambdaQueryChainWrapper<User> lq = this.lambdaQuery();
        lq.in(User::getUserId, userIdList);
        lq.eq(StringUtils.isNotEmpty(searchVo.getRealName()), User::getRealName, searchVo.getRealName());
        lq.eq(StringUtils.isNotEmpty(searchVo.getMobile()), User::getMobile, searchVo.getMobile());
        lq.page(page);

        List<User> userList = page.getRecords();

        //转换简单对象
        List<UserMapstruct.UserAndCompanySimpleVo> userAndCompanySimpleVoList = new ArrayList<>(userList.size());
        userList.stream().forEach(user -> {
            //部门信息
            List<CompanyDepartmentEmployee> userCompanyDepartmentEmployeeList = companyDepartmentEmployeeMap.get(user.getUserId());
            //用户主职信息
            List<CompanyDepartmentEmployee> mainCompanyDepartmentEmployeeList = userCompanyDepartmentEmployeeList.stream().filter(d -> !d.getIsPartTimeJob()).collect(Collectors.toList());
            //用户兼职信息
            List<CompanyDepartmentEmployee> partTimeJobCompanyDepartmentEmployeeList = userCompanyDepartmentEmployeeList.stream().filter(d -> d.getIsPartTimeJob()).collect(Collectors.toList());

            //用户是否兼职
            boolean userIsPartTimeJob = false;
            CompanyDepartmentEmployee companyDepartmentEmployee = null;
            if (ListUtils.isExistsEle(mainCompanyDepartmentEmployeeList)) {
                userIsPartTimeJob = false;
                companyDepartmentEmployee = mainCompanyDepartmentEmployeeList.get(0);
            } else if (ListUtils.isExistsEle(partTimeJobCompanyDepartmentEmployeeList)) {
                userIsPartTimeJob = true;
                companyDepartmentEmployee = partTimeJobCompanyDepartmentEmployeeList.get(0);
            } else {
                throw CommonException.build(ErrMsgConstant.EMPLOYEE_INFO_NOT_EXISTS);
            }
            List<String> userAllCompanyNameList = baseCompanyService.getUserAllCompanyNameListByUserId(user.getUserId(), true);

            UserMapstruct.UserAndCompanySimpleVo userAndCompanySimpleVo = new UserMapstruct.UserAndCompanySimpleVo();
            userAndCompanySimpleVo.setUserId(user.getUserId());
            userAndCompanySimpleVo.setRealName(user.getUserId());
            userAndCompanySimpleVo.setAvatarUrl(user.getAvatarUrl());
            userAndCompanySimpleVo.setAccountStatus(user.getAccountStatus());
            userAndCompanySimpleVo.setSex(user.getSex());
            userAndCompanySimpleVo.setCompanyId(company.getCompanyId());
            userAndCompanySimpleVo.setCompanyName(company.getCompanyName());
            userAndCompanySimpleVo.setCompanyDepartmentId(StringUtils.EMPTY);
            userAndCompanySimpleVo.setCompanyDepartmentName(StringUtils.EMPTY);
            userAndCompanySimpleVo.setUserPartTimeJobCompanyNameList(userAllCompanyNameList);
            userAndCompanySimpleVo.setIsCompanyDepartmentPrincipal(userIsPartTimeJob);
            userAndCompanySimpleVo.setIsCompanyAdmin(user.getUserId().equals(companyAdminUserId));
            userAndCompanySimpleVo.setJobName(companyDepartmentEmployee.getJobName());
            userAndCompanySimpleVoList.add(userAndCompanySimpleVo);
        });
        page.setRecords(userAndCompanySimpleVoList);
        return userAndCompanySimpleVoList;
    }


    /**
     * 重置密码
     */
    @Transactional(rollbackFor = Exception.class)
    public String resetPassword(
            @NonNull String userId
    ) {
        //1.获取用户实体
        User user = this.getById(userId);
        ObjectUtils.isNullThrow(user, "查询不到用户信息,请联系管理员");

        //2.重置密码加密
        String userPwd = PasswordUtils.generateUserPwd(user.getRealName(), user.getMobile());
        String defaultPwdEncrypt = EncryptDecryptUtils.md5Encrypt(userPwd);
        this.lambdaUpdate()
                .eq(User::getUserId, userId)
                .set(User::getPwd, defaultPwdEncrypt)
                .set(User::getIsNeedForceUpPwd, true)
                .update();
        //清空账号登录错误的次数
        AccountUtils.deleteAccountErrorLoginCount(user.getAccount());
        return userPwd;
    }


    /**
     * 更新用户信息
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateUserInfo(
            @NonNull UserMapstruct.ChangeUserInfoVo saveVo
    ) {
        SpringBootValidateUtils.validate(saveVo);
        String userId = saveVo.getUserId();
        User user = this.getById(userId);
        ObjectUtils.isNullThrow(saveVo, "用户不存在");

        //手机号不为空,就修改手机号
        if (StringUtils.isNotEmpty(saveVo.getMobile())) {
            //判断修改的手机号是否已注册
            boolean isExistsMobile = this.mobileExists(user.getMobile(), userId);
            BooleanUtils.isTrueThrow(isExistsMobile, "此账号已注册，请重新输入");
        }

        //用户名不为空就修改名称
        if (StringUtils.isNotEmpty(saveVo.getRealName())) {
            user.setRealName(saveVo.getRealName());
        }
        //头像不能为空就修改头像
        if (StringUtils.isNotEmpty(saveVo.getAvatarUrl())) {
            user.setAvatarUrl(saveVo.getAvatarUrl());
        }
        //身份证号不为空就修改身份证号
        if (StringUtils.isNotEmpty(saveVo.getIdCard())) {
            user.setIdCard(saveVo.getIdCard());
            user.setBirthday(UserUtils.getBirthdayByIdCard(saveVo.getIdCard()));
            user.setSex(UserUtils.getSexByIdCard(saveVo.getIdCard()));
        }
        //手机号不为空就修改手机号和账号
        if (StringUtils.isNotEmpty(saveVo.getMobile())) {
            user.setMobile(saveVo.getMobile());
            user.setAccount(saveVo.getMobile());
        }
        user.updateById();
    }

    /**
     * 是否平台用户
     *
     * @param userId 用户ID
     */
    public boolean isAllowLoginPlatform(String userId) {
        List<AllowLoginPlatformCompany> allowLoginPlatformCompanyList = baseAllowLoginPlatformCompanyService.lambdaQuery()
                .select(AllowLoginPlatformCompany::getCompanyId)
                .list();

        if (ListUtils.isNotExistsEle(allowLoginPlatformCompanyList)) {
            return false;
        }
        //公司ID
        List<String> allowLogiCompanyIdList = allowLoginPlatformCompanyList.stream().map(allowLoginPlatformCompany -> allowLoginPlatformCompany.getCompanyId()).collect(Collectors.toList());
        //员工信息
        boolean isExistsAllowLoginCompanyEmployee = baseCompanyEmployeeService.lambdaQuery()
                .eq(CompanyEmployee::getUserId, userId)
                .in(CompanyEmployee::getCompanyId, allowLogiCompanyIdList)
                .count() > 0;
        return isExistsAllowLoginCompanyEmployee;
    }

    public UserMapstruct.UserVo getUserInfo(String userId) {

        User user = this.lambdaQuery().eq(User::getUserId, userId).one();

        if (user == null) {
            throw CommonException.build("用户信息为空");
        }

        UserMapstruct.UserVo userVo = JsonUtils.convertObject(user, UserMapstruct.UserVo.class);
        userVo.setRegSuccess(true);

        List<CompanyEmployee> employees = baseCompanyEmployeeService.getByUserId(userId, false);

        if (employees.isEmpty()) {
            throw CommonException.build("用户未创建公司");
        }

        List<String> empIds = employees.stream().map(CompanyEmployee::getCompanyId).collect(Collectors.toList());

        List<Company> companies = baseCompanyService.lambdaQuery().in(Company::getCompanyId, empIds).list();
        List<Company> isNoPass = companies.stream().filter(d -> d.getAuditStatus() != EnumAuditStatus.Pass).collect(Collectors.toList());

        if (!isNoPass.isEmpty()) {
            userVo.setRegSuccess(false);
        }

        return userVo;
    }


}
